﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WinFormsApp1.Neo4jGrid;
using WinFormsApp1.Websocket;

namespace WinFormsApp1
{
    public partial class Neo4JSingleViewForm : UserControl
    {
        private Neo4JServe m_serve;
        private WSocket m_wsServe;
        public Neo4JSingleViewForm()
        {
            InitializeComponent();
        }

        #region 1-1 获得配置
        private string ProjectName
        {
            get
            {
                return this.comboBox1.Text;
            }
        }
        private string EntityTableName
        {
            get
            {
                if (this.comboBox1.SelectedIndex == 0)
                {
                    return "SimpleTaskEntity";
                }
                return null;
            }
        }
        private string StartEntityName
        {
            get
            {
                if (this.comboBox1.SelectedIndex == 0)
                {
                    return "AgCIM 3.5";
                }
                return null;
            }
        }
        #endregion

        #region 1-1 获得初始节点
        private async void toolStripButton1_ClickAsync(object sender, EventArgs e)
        {
            var query = m_serve.Client.Cypher
                .Match("(startNode:" + EntityTableName + " {name: $name})")
                .OptionalMatch("(startNode)-[relation]-(relatedNode)")
                .WithParam("name", StartEntityName)
                .Return((startNode, relation, relatedNode) => new
                {
                    StartNode = startNode.As<SimpleTaskEntity>(),
                    Relation = relation.As<CommonRelation>(),
                    RelatedNode = relatedNode.As<SimpleTaskEntity>()
                });

            var results = await query.ResultsAsync;

            TreeNode tn = new TreeNode(StartEntityName);
            this.treeView1.Nodes.Add(tn);
            foreach (var ri in results)
            {
                TreeNode tn2 = new TreeNode(ri.Relation.type + "  " + ri.RelatedNode.name);
                tn2.Tag = ri.RelatedNode;
                tn.Nodes.Add(tn2);
            }
        }
        private async Task<string> GetFirstNode(string entityType,string startEntityName)
        {
            if (entityType == "AgTask")
            {
                var t=await GetFirstNodeOfAgTask();
                return t;
            }
            if (entityType == "Grid")
            {
                return await GetFirstNodeOfGrid(startEntityName);
            }
            return null;
        }
        private async Task<string> GetFirstNodeOfAgTask()
        {
            var query = m_serve.Client.Cypher
                .Match("(startNode:SimpleTaskEntity {name: $name})")
                .OptionalMatch("(startNode)-[relation]-(relatedNode)")
                .WithParam("name", "AgCIM 3.5")
                .Return((startNode, relation, relatedNode) => new
                {
                    StartNode = startNode.As<SimpleTaskEntity>(),
                    Relation = relation.As<CommonRelation>(),
                    RelatedNode = relatedNode.As<SimpleTaskEntity>()
                });

            var results = await query.ResultsAsync;

            KnowlgeMap knowlgeMap = new KnowlgeMap();
            knowlgeMap.Initialize();
            var index = 0;
            foreach (var ri in results)
            {
                if (index == 0)
                {
                    knowlgeMap.AddEntity(ri.StartNode.ToCommonEntity());
                    index++;
                }

                knowlgeMap.AddEntity(ri.RelatedNode.ToCommonEntity());
                var rt = ri.Relation.type;
                if (string.IsNullOrEmpty(rt)) rt = "产品目的";
                knowlgeMap.AddRelation(ri.StartNode.ToCommonEntity(), ri.RelatedNode.ToCommonEntity(), rt);
            }
            return JsonConvert.SerializeObject(knowlgeMap);
        }
        private async Task<string> GetFirstNodeOfGrid( string startEntityName)
        {
            var query = m_serve.Client.Cypher
                .Match("(startNode:"+ GridNameUtils .FromEntityTableName+ "  {name: $name})")
                .OptionalMatch("(startNode)-[relation]-(relatedNode)")
                .WithParam("name", startEntityName)
                .Return((startNode, relation, relatedNode) => new
                {
                    StartNode = startNode.As<CommonEntity>(),
                    Relation = relation.As<CommonRelation>(),
                    EndNode = relatedNode.As<GridEntity>()
                });

            var results = await query.ResultsAsync;

            KnowlgeMap knowlgeMap = new KnowlgeMap();
            knowlgeMap.Initialize();
            var index = 0;
            foreach (var ri in results)
            {
                ri.StartNode.Check();
                if (index == 0)
                {
                    knowlgeMap.AddEntity(ri.StartNode);
                    index++;
                }
                var end1 = ri.EndNode;
                var end= end1.ToCommonEntity();
                end.Check();
                knowlgeMap.AddEntity(end);
                var rt = ri.Relation.type;
                if (string.IsNullOrEmpty(rt)) rt = "产品目的";
                knowlgeMap.AddRelation(ri.StartNode, end, rt);
            }
            return JsonConvert.SerializeObject(knowlgeMap);
        }
        #endregion


        private void Neo4JSingleViewForm_Load(object sender, EventArgs e)
        {
            m_serve = new Neo4JServe();
            m_serve.Initialize();
        }

        #region 获得下一个节点
        private async void treeView1_NodeMouseDoubleClickAsync(object sender, TreeNodeMouseClickEventArgs e)
        {
            var con = e.Node.Tag as SimpleTaskEntity; if (con == null) { return; }

            var query = m_serve.Client.Cypher
                .Match("(startNode:SimpleTaskEntity {id: $id})")
                .OptionalMatch("(startNode)-[relation]-(relatedNode)")
                .WithParam("id", con.id)
                .Return((startNode, relation, relatedNode) => new
                {
                    StartNode = startNode.As<SimpleTaskEntity>(),
                    Relation = relation.As<CommonRelation>(),
                    RelatedNode = relatedNode.As<SimpleTaskEntity>()
                });

            var results = await query.ResultsAsync;

            TreeNode tn = e.Node;
            foreach (var ri in results)
            {
                TreeNode tn2 = new TreeNode(ri.Relation.type + "  " + ri.RelatedNode.name);
                tn2.Tag = ri.RelatedNode;
                tn.Nodes.Add(tn2);
            }
        }
        private async Task<string> GetNextNodes(string entityId)
        {
            var query = m_serve.Client.Cypher
                .Match("(startNode:SimpleTaskEntity {id: $id})")
                .OptionalMatch("(startNode)-[relation]-(relatedNode)")
                .WithParam("id", entityId)
                .Return((startNode, relation, relatedNode) => new
                {
                    StartNode = startNode.As<SimpleTaskEntity>(),
                    Relation = relation.As<CommonRelation>(),
                    RelatedNode = relatedNode.As<SimpleTaskEntity>()
                });

            var results = await query.ResultsAsync;

            KnowlgeMap knowlgeMap = new KnowlgeMap();
            knowlgeMap.Initialize();
            var index = 0;
            foreach (var ri in results)
            {
                if (index == 0)
                {
                    knowlgeMap.AddEntity(ri.StartNode.ToCommonEntity());
                    index++;
                }

                knowlgeMap.AddEntity(ri.RelatedNode.ToCommonEntity());
                var rt = ri.Relation.type;
                if (string.IsNullOrEmpty(rt)) rt = "产品目的";
                knowlgeMap.AddRelation(ri.StartNode.ToCommonEntity(), ri.RelatedNode.ToCommonEntity(), rt);
            }
            return JsonConvert.SerializeObject(knowlgeMap);
        }
        #endregion


        #region 2-1 启动WebSocket
        private void button1_Click(object sender, EventArgs e)
        {
            this.button1.Text = "已开启WebSocket";

            m_wsServe = new WSocket();
            WSocket.OnGetMsg += WSocket_OnGetMsgAsync;
            m_wsServe.Start();
        } 
        #endregion

        #region 2-2 获得WebSocket消息
        private async void WSocket_OnGetMsgAsync(object? sender, WSEvent e)
        {
            var inputs = sender.ToString();
            var colonIndex = inputs.IndexOf(':');
            var command = inputs.Substring(0, colonIndex);
            var json = inputs.Substring(colonIndex + 1);
            //反序列化JSON字符串
            var args = JsonConvert.DeserializeObject(json) as JToken;

            if (command == "getFirstNode")
            {
                var entityTypeName=args["entityType"].ToString();
                var startEntityName=args["startEntityName"].ToString();
                e.OutputArgs = await GetFirstNode(entityTypeName,startEntityName);
                e.OnProcess(e.OutputArgs, null);
            }
            if (sender=="getNextNode")
            {
                var currentNode=args["entityId"].ToString();
                e.OutputArgs = await GetNextNodes(currentNode);
                e.OnProcess(e.OutputArgs, null);
            }
        }
        #endregion

        
    }
}
